#include "orangepch.h"
#include "WindowsWindow.h"
#include <GLFW/glfw3.h>
#include "Platform/OpenGL/OpenGLContext.h"
namespace Orange
{
    static bool s_GLFWinitlized = false;

    Window *Window::Create(const WindowProps &props)
    {
        return new WindowsWindow(props);
    }

    WindowsWindow::WindowsWindow(const WindowProps &props)
    {
        Init(props);
    }

    WindowsWindow::~WindowsWindow()
    {
    }
    void WindowsWindow::Init(const WindowProps &props)
    {

        m_Data.m_Width = props.m_Width;
        m_Data.m_Height = props.m_Height;
        m_Data.m_Title = props.m_Title;

        if (!s_GLFWinitlized)
        {
            int success = glfwInit();
            if (!success)
            {
                std::cout << "Could not intialize GLFW!" << std::endl;
                ORANGE_CORE_ERROR("Could not intialize GLFW!");
                return;
            }
        }

        ORANGE_CORE_INFO("Create Window");
        m_Window = glfwCreateWindow((int)m_Data.m_Width, (int)m_Data.m_Height, m_Data.m_Title.c_str(), nullptr, nullptr);
        glfwSetWindowUserPointer(m_Window, &m_Data);

        m_Context = new OpenGLContext(m_Window);
        m_Context->Init();

        SetSync(true);

        ORANGE_CORE_INFO("Opengl info:");
        ORANGE_CORE_INFO("vendor: {0}", glGetString(GL_VENDOR));
        ORANGE_CORE_INFO("renderer: {0}", glGetString(GL_RENDERER));
        ORANGE_CORE_INFO("version: {0}", glGetString(GL_VERSION));

        // 窗口关闭
        glfwSetWindowCloseCallback(m_Window, [](GLFWwindow *window)
                                   {
                                    WindowData &data = *(WindowData *)glfwGetWindowUserPointer(window);
                                    WindowCloseEvent e;
                                    data.Callback(e); });
        // 文本流输入
        glfwSetCharCallback(m_Window, [](GLFWwindow *window, unsigned int code)
                            {
                            WindowData &data = *(WindowData *)glfwGetWindowUserPointer(window);
                            KeyTypeEvent e(code);
                            data.Callback(e); });
        // 窗口改变
        glfwSetWindowSizeCallback(m_Window, [](GLFWwindow *window, int width, int height)
                                  {
                                    WindowData &data = *(WindowData *)glfwGetWindowUserPointer(window);
                                    WindowResizeEvent e(width,height);
                                    data.Callback(e); });
        // 按键事件
        glfwSetKeyCallback(m_Window, [](GLFWwindow *window, int key, int scancode, int action, int mods)
                           {
                            WindowData &data = *(WindowData *)glfwGetWindowUserPointer(window);

                            switch (action)
                            {
                            case GLFW_PRESS:
                              {
                                KeyPressEvent e(key , 0);
                                data.Callback(e);
                                break;
                              }
                            case GLFW_RELEASE:
                             {
                                KeyReleasedEvent e(key);
                                data.Callback(e);
                                break;
                             }
                            case GLFW_REPEAT:
                              {
                                KeyPressEvent e(key , 1);
                                data.Callback(e);
                                break;
                              }
                        
                            } });

        // 鼠标滚轮事件

        glfwSetScrollCallback(m_Window, [](GLFWwindow *window, double xoffset, double yoffset)
                              {
                              WindowData &data = *(WindowData *)glfwGetWindowUserPointer(window);
                              MouseScrollEvent e((float)xoffset , (float)yoffset );
                              data.Callback(e); });

        // 鼠标移动事件

        glfwSetCursorPosCallback(m_Window, [](GLFWwindow *window, double xpos, double ypos)
                                 {
                                WindowData &data = *(WindowData *)glfwGetWindowUserPointer(window);
                                MouseMoveEvent e((float)xpos , (float)ypos );
                                data.Callback(e); });

        // 鼠标点击事件

        glfwSetMouseButtonCallback(m_Window, [](GLFWwindow *window, int button, int action, int mods)
                                   {
                                    WindowData &data = *(WindowData *)glfwGetWindowUserPointer(window);

                                    switch (action)
                                    {
                                    case GLFW_PRESS:
                                    {
                                        MouseButtonPressedEvent e(button);
                                        data.Callback(e);
                                        break;
                                    }
                                    
                                    case GLFW_RELEASE:
                                    {
                                        MouseButtonReleasedEvent e(button);
                                        data.Callback(e);
                                        break;
                                    }
                                
                                    } });
    }

    void WindowsWindow::OnUpdate()
    {
        glfwPollEvents();

        m_Context->Swap();
    }

    const unsigned int WindowsWindow::GetWidth() const
    {
        return m_Data.m_Width;
    }

    const unsigned int WindowsWindow::GetHeight() const
    {
        return m_Data.m_Height;
    }

    void WindowsWindow::SetSync(bool enable)
    {
        if (enable)
        {
            glfwSwapInterval(1);
        }
        else
        {
            glfwSwapInterval(0);
        }
        m_Data.Vsync = enable;
    };
    const bool WindowsWindow::IsSync() const
    {
        return m_Data.Vsync;
    };

    // 获取当前窗口
    void *WindowsWindow::GetNativeWindow() const
    {
        return m_Window;
    };

    // 获取当前窗口
    void WindowsWindow::ShutDown()
    {
        glfwDestroyWindow(m_Window);
    };

}